package com.inspector.app.di.location;


import android.location.Location;
import android.location.LocationManager;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.amap.api.location.AMapLocation;
import com.inspector.app.di.vo.LocationPosition;
import com.inspector.app.util.CoordinateTransformUtils;
import com.inspector.app.util.LogUtil;
import com.inspector.app.util.UUIDGenerator;
import com.mapsforge.map.EfbLatLngPoint;

import kotlin.jvm.Volatile;


/**
 * 将UpLoadDataService中的定位抽出来,用于根据机型决定使用那种定位方式
 *
 * @author CodeK 2023/7/3
 */
public class LocationInstance {

    private String TAG = "定位结果处理";

    private volatile Location lastKnownLocation; //[最后一次可用的定位]
    public void setLastKnownLocation(Location lastKnownLocation) {
        this.lastKnownLocation = lastKnownLocation;
    }

    @Nullable
    public Location getLastKnownLocation() {
        return lastKnownLocation;
    }


    private boolean providerEnabled = false; //[定位是否可用]
    public void setProviderEnabled(boolean providerEnabled) {
        this.providerEnabled = providerEnabled;
    }
    public boolean isProviderEnabled() {
        return providerEnabled;
    }

    private boolean providerOpened = false; //[定位开关是否打开]
    public void setProviderOpened(boolean providerOpened) {
        this.providerOpened = providerOpened;
    }
    public boolean isProviderOpened() {
        return providerOpened;
    }


    /**
     * 计算结果回调处理
     *
     * @param locationClient
     * @param location
     * @param lastKnownLocation
     */
    private final long minInterval = 2000L; //[补点时间间隔]
    private long wgs84LocationTimeMillis = 0L;
    private long gdLocationTimeMillis = 0L;
    private long singlePositionTimeMillis = 0L; //[单一原生或华为定位或高德定位服务时间戳]
    private long multiplePositionTimeMillis = 0L;
//    private final LimitQueue<LocationPosition> locationQueue = new LimitQueue<>(3);
    public Location onLocationChanged(@NonNull LocationClient locationClient, @NonNull Location location, boolean lastKnownLocation) {
        if (lastKnownLocation) return location; //[从缓存中拿到的点]
        boolean multipleLocationType = locationClient.getMapLocationType() == CustomLocationType.LOCATION_MULTIPLE;
        if (!multipleLocationType) { //[默认定位或高德定位]
            if (singlePositionTimeMillis == 0L) singlePositionTimeMillis = System.currentTimeMillis();
            LogUtil.e(TAG, "onLocationChanged 定位方式:"+ (locationClient.getMapLocationType().name())
                    + " 定位间隔:" + (System.currentTimeMillis() - singlePositionTimeMillis) + " getLatitude:" + location.getLatitude() + " getLongitude:" + location.getLongitude() + " lastKnownLocation:" + lastKnownLocation);
            singlePositionTimeMillis = System.currentTimeMillis();
            return location;
        }

        if (multiplePositionTimeMillis == 0L) multiplePositionTimeMillis = System.currentTimeMillis();
        long timeMillis = System.currentTimeMillis() - multiplePositionTimeMillis;
        if (location instanceof CustomLocation
                && ((CustomLocation) location).getCoordinateType() == CustomCoordinateType.GAODE) { //[高德坐标系]
            if (gdLocationTimeMillis == 0L) gdLocationTimeMillis = System.currentTimeMillis();
            LogUtil.e(TAG, "onLocationChanged 定位方式:融合定位-高德"
                    + " 定位间隔:" + timeMillis
                    + " 高德定位间隔:" + (System.currentTimeMillis() - gdLocationTimeMillis)
                    + " WGS84定位间隔:" + (System.currentTimeMillis() - wgs84LocationTimeMillis)
                    + " 航向:" + location.getBearing()
                    + " 海拔:" + location.getAltitude()
                    + " getLatitude:" + location.getLatitude() + " getLongitude:" + location.getLongitude());
            multiplePositionTimeMillis = System.currentTimeMillis();
            gdLocationTimeMillis = System.currentTimeMillis();

            // TODO: 2024/6/26 根据结果计算是否要补点操作, 如何减小转换坐标后的误差???
            if (System.currentTimeMillis() - wgs84LocationTimeMillis >= minInterval) {
//                if (locationQueue.size() != locationQueue.getLimit()) return location;
//                Object[] queueArray = locationQueue.toArray();
//                LocationPosition firstItem = (LocationPosition) queueArray[0];
//                LocationPosition middleItem = (LocationPosition) queueArray[1];
//                LocationPosition lastItem = (LocationPosition) queueArray[2];
//                double firstDistance = TopoUtils.distance(firstItem.getLatLngPoint(), middleItem.getLatLngPoint());
//                double secondDistance = TopoUtils.distance(firstItem.getLatLngPoint(), lastItem.getLatLngPoint());
//                double thirdDistance = TopoUtils.distance(firstItem.getLatLngPoint(), new EfbLatLngPoint(location.getLatitude(), location.getLongitude()));
//                if (thirdDistance > secondDistance && thirdDistance > firstDistance) {
//                    locationQueue.offer(swapLocationPosition(location));
//                    return location;
//                }
                return location;
            } else return null;
        } else { //[WGS84坐标系]
            if (wgs84LocationTimeMillis == 0L) wgs84LocationTimeMillis = System.currentTimeMillis();
            LogUtil.e(TAG, "onLocationChanged 定位方式:融合定位-WGS84"
                    + " 定位间隔:" + timeMillis
                    + " 高德定位间隔:" + (System.currentTimeMillis() - gdLocationTimeMillis)
                    + " WGS84定位间隔:" + (System.currentTimeMillis() - wgs84LocationTimeMillis)
                    + " 航向:" + location.getBearing()
                    + " 海拔:" + location.getAltitude()
                    + " getLatitude:" + location.getLatitude() + " getLongitude:" + location.getLongitude());
            multiplePositionTimeMillis = System.currentTimeMillis();
            wgs84LocationTimeMillis = System.currentTimeMillis();
//            locationQueue.offer(swapLocationPosition(location));
            return location;
        }
    }


    public static LocationPosition swapLocationPosition(Location location) {
        LocationPosition position = new LocationPosition();
        position.setId(UUIDGenerator.generate());
        position.setLocationTime(System.currentTimeMillis());
        position.setNanoTime(System.nanoTime());
        position.setLatLngPoint(new EfbLatLngPoint(location.getLatitude(), location.getLongitude()));
        position.setAltitude(location.getAltitude());
        position.setBearing(location.getBearing());
        position.setSpeedEnabled(location.hasSpeed());
        position.setCurrentSpeed(location.getSpeed());
        position.setHorizontalAccuracyMeters(location.getAccuracy()); //[水平精确]
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (location.hasVerticalAccuracy()) {
                position.setVerticalAccuracyMeters(location.getVerticalAccuracyMeters()); //[竖直精确]
            }
            if (location.hasSpeedAccuracy()) {
                position.setSpeedAccuracyMetersPerSecond(location.getSpeedAccuracyMetersPerSecond()); //[速度精确]
            }
            if (location.hasBearingAccuracy()) {
                position.setBearingAccuracyDegrees(location.getBearingAccuracyDegrees()); //[角度精确]
            }
        }
        // [更多]

        return position;
    }

    public static CustomLocation swapAMapLocation(@NonNull AMapLocation aMapLocation) {
        //[定位类型对照表] https://lbs.amap.com/api/android-location-sdk/guide/utilities/location-type
        int locationType = aMapLocation.getLocationType();
        CustomLocation location = new CustomLocation((locationType == 5 || locationType == 6)
                ? LocationManager.NETWORK_PROVIDER : LocationManager.GPS_PROVIDER);
        double[] latLng = CoordinateTransformUtils.gcj02towgs84(aMapLocation.getLongitude(), aMapLocation.getLatitude());
        location.setCoordinateType(CustomCoordinateType.GAODE);
        location.setLatitude(latLng[1]);
        location.setLongitude(latLng[0]);

        location.setAltitude(aMapLocation.getAltitude());
        location.setBearing(aMapLocation.getBearing());
        location.setAccuracy(aMapLocation.getAccuracy());
        location.setSpeed(aMapLocation.getSpeed());
        location.setAccuracy(aMapLocation.getAccuracy()); //[水平精确]
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (aMapLocation.hasVerticalAccuracy()) {
                location.setVerticalAccuracyMeters(aMapLocation.getVerticalAccuracyMeters()); //[竖直精确]
            }
            if (aMapLocation.hasSpeedAccuracy()) {
                location.setSpeedAccuracyMetersPerSecond(aMapLocation.getSpeedAccuracyMetersPerSecond()); //[速度精确]
            }
            if (aMapLocation.hasBearingAccuracy()) {
                location.setBearingAccuracyDegrees(aMapLocation.getBearingAccuracyDegrees()); //[角度精确]
            }
        }
        // [更多]

        return location;
    }


    private volatile static LocationInstance instance;
    public static LocationInstance getInstance() {
        if (instance == null) {
            synchronized (LocationInstance.class) {
                if (instance == null) {
                    instance = new LocationInstance();
                }
            }
        }
        return instance;
    }



}
